<template>
  <div class="coloring-app">
    <div class="tools-panel">
      <div class="color-picker">
        <h3>选择颜色</h3>
        <div class="color-grid">
          <div 
            v-for="(color, index) in colors" 
            :key="index" 
            class="color-item"
            :style="{ backgroundColor: color }"
            @click="selectColor(color)"
            :class="{ active: currentColor === color }"
          ></div>
        </div>
        <input type="color" v-model="customColor" @change="selectColor(customColor)">
      </div>
      <div class="actions">
        <button @click="resetCanvas" class="action-btn">重置</button>
        <button @click="downloadImage" class="action-btn">下载</button>
      </div>
    </div>
    <div class="canvas-container">
      <canvas ref="canvasRef" width="600" height="600"></canvas>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
// 获取插件提供的 fabric 实例
const { $fabric } = useNuxtApp();
const canvasRef = ref<HTMLCanvasElement | null>(null);
let canvas: any = null;

// 颜色选择器
const colors = [
  '#FF0000', '#FF7F00', '#FFFF00', '#00FF00', 
  '#0000FF', '#4B0082', '#9400D3', '#FF69B4',
  '#FFC0CB', '#FFD700', '#32CD32', '#87CEEB',
  '#8A2BE2', '#FF6347', '#00FFFF', '#FFFFFF',
  '#000000', '#808080', '#A52A2A', '#F5F5DC'
];

const currentColor = ref('#FF0000');
const customColor = ref('#FF0000');

// 选择颜色
const selectColor = (color: string) => {
  currentColor.value = color;
  customColor.value = color;
};

// 重置画布
const resetCanvas = () => {
  loadImage();
};

// 下载图片
const downloadImage = () => {
  if (canvas) {
    const dataURL = canvas.toDataURL({
      format: 'png',
      quality: 1
    });
    
    const link = document.createElement('a');
    link.download = '我的填色作品.png';
    link.href = dataURL;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }
};

// 加载图片并设置填色区域
const loadImage = () => {
  if (!canvas) return;
  
  // 清空画布
  canvas.clear();
  
  // 获取图片的正确路径
  const imagePath = new URL('@/assets/images/atm.png', import.meta.url).href;
  
  // 加载图片
  $fabric.Image.fromURL(imagePath, {
    crossOrigin: 'anonymous'
  })
  .then((img: any) => {
    // 调整图片大小以适应画布
    const scale = Math.min(
      canvas.width / img.width,
      canvas.height / img.height
    );
    
    img.set({
      scaleX: scale,
      scaleY: scale,
      originX: 'center',
      originY: 'center',
      left: canvas.width / 2,
      top: canvas.height / 2,
      selectable: false // 禁止选择图片
    });
    
    // 将图片添加到画布
    canvas.add(img);
    canvas.renderAll();
  })
  .catch((error: any) => {
    console.error('加载图片失败:', error);
    tryAlternativeImageLoading();
  });
};

// 备用图片加载方法
const tryAlternativeImageLoading = () => {
  // 尝试直接从assets目录加载
  const img = new Image();
  img.crossOrigin = 'anonymous';
  img.onload = function() {
    const fabricImage = new $fabric.Image(img);
    
    // 调整图片大小以适应画布
    const scale = Math.min(
      canvas.width / fabricImage.width,
      canvas.height / fabricImage.height
    );
    
    fabricImage.set({
      scaleX: scale,
      scaleY: scale,
      originX: 'center',
      originY: 'center',
      left: canvas.width / 2,
      top: canvas.height / 2,
      selectable: false
    });
    
    canvas.add(fabricImage);
    canvas.renderAll();
  };
  
  img.onerror = function(err) {
    console.error('备用加载方法也失败了:', err);
  };
  
  // 尝试不同的路径
  img.src = '/assets/images/atm.png';
};

// 辅助函数：获取像素点的颜色
const getColorAtPixel = (data: Uint8ClampedArray, width: number, x: number, y: number) => {
  const index = (y * width + x) * 4;
  return {
    r: data[index],
    g: data[index + 1],
    b: data[index + 2],
    a: data[index + 3]
  };
};

// 辅助函数：带容差的颜色匹配
const colorsMatchWithTolerance = (a: any, b: any, tolerance: number) => {
  return (
    Math.abs(a.r - b.r) <= tolerance &&
    Math.abs(a.g - b.g) <= tolerance &&
    Math.abs(a.b - b.b) <= tolerance
  );
};

// 辅助函数：检查是否为黑色或接近黑色
const isBlackOrNearBlack = (color: any) => {
  return color.r < 30 && color.g < 30 && color.b < 30;
};

// 创建填充路径
const createFillPath = (x: number, y: number, color: string) => {
  if (!canvas) return null;
  
  // 获取画布的原始图像
  const originalImage = canvas.getObjects()[0];
  if (!originalImage) return null;
  
  // 创建临时画布用于分析
  const tempCanvas = document.createElement('canvas');
  tempCanvas.width = canvas.width;
  tempCanvas.height = canvas.height;
  const tempCtx = tempCanvas.getContext('2d');
  if (!tempCtx) return null;
  
  // 将原图像渲染到临时画布
  tempCtx.drawImage(originalImage.getElement(), 0, 0, canvas.width, canvas.height);
  
  // 获取点击位置的颜色
  const targetColor = getColorAtPixel(tempCtx.getImageData(0, 0, canvas.width, canvas.height).data, canvas.width, Math.floor(x), Math.floor(y));
  
  // 避免替换黑色线条
  if (isBlackOrNearBlack(targetColor)) {
    console.log('点击了黑色线条，不进行填充');
    return null;
  }
  
  // 使用洪水填充算法找出区域边界点
  const boundaryPoints = findBoundaryPoints(tempCtx, Math.floor(x), Math.floor(y), targetColor);
  
  if (boundaryPoints.length < 3) {
    console.log('找不到足够的边界点来创建路径');
    return null;
  }
  
  // 创建 Fabric.js 多边形路径
  const path = new $fabric.Polygon(boundaryPoints.map(p => ({
    x: p.x,
    y: p.y
  })), {
    fill: color,
    selectable: false,
    evented: false,
    opacity: 1.0,
    perPixelTargetFind: true
  });
  
  return path;
};

// 找出区域边界点 - 使用扫描线填充算法
const findBoundaryPoints = (ctx: CanvasRenderingContext2D, startX: number, startY: number, targetColor: any) => {
  const width = ctx.canvas.width;
  const height = ctx.canvas.height;
  const imageData = ctx.getImageData(0, 0, width, height);
  const data = imageData.data;
  
  // 创建访问标记数组
  const visited = new Array(width * height).fill(false);
  const stack = [{x: startX, y: startY}];
  const points = [];
  
  // 颜色容差
  const tolerance = 30;
  
  while (stack.length > 0) {
    const {x, y} = stack.pop();
    
    // 检查边界
    if (x < 0 || x >= width || y < 0 || y >= height) continue;
    
    // 计算像素索引
    const index = (y * width + x) * 4;
    
    // 检查是否已访问
    if (visited[y * width + x]) continue;
    
    // 获取当前像素颜色
    const currentColor = {
      r: data[index],
      g: data[index + 1],
      b: data[index + 2],
      a: data[index + 3]
    };
    
    // 检查是否匹配目标颜色
    if (!colorsMatchWithTolerance(currentColor, targetColor, tolerance)) continue;
    
    // 标记为已访问
    visited[y * width + x] = true;
    
    // 添加到结果点
    points.push({x, y});
    
    // 添加相邻像素到栈中
    stack.push({x: x + 1, y: y});
    stack.push({x: x - 1, y: y});
    stack.push({x: x, y: y + 1});
    stack.push({x: x, y: y - 1});
  }
  
  // 简化边界点
  return simplifyBoundaryPoints(points, 5);
};

// 简化边界点
const simplifyBoundaryPoints = (points: {x: number, y: number}[], step: number) => {
  if (points.length <= 3) return points;
  
  const simplified = [];
  for (let i = 0; i < points.length; i += step) {
    simplified.push(points[i]);
  }
  
  // 确保至少有 3 个点来形成多边形
  if (simplified.length < 3) {
    return points.filter((_, i) => i % Math.max(1, Math.floor(points.length / 3)) === 0);
  }
  
  return simplified;
};

// 在组件中添加填色功能
const applyColorToArea = (x: number, y: number, color: string) => {
  if (!canvas) return;
  
  // 获取点击的区域边界
  console.log('开始填色:', color);
  
  // 使用 Fabric.js 的路径创建一个填充区域
  const path = createFillPath(x, y, color);
  if (path) {
    // 移除已存在的填充路径
    canvas.forEachObject(obj => {
      if (obj.type === 'polygon') {
        canvas.remove(obj);
      }
    });
    
    canvas.add(path);
    canvas.renderAll();
  }
};

// 初始化画布时添加事件监听
onMounted(() => {
  if (canvasRef.value) {
    // 初始化 Fabric.js 画布
    canvas = new $fabric.Canvas(canvasRef.value, {
      backgroundColor: '#ffffff',
      selection: false,
      perPixelTargetFind: true
    });
    
    // 加载图片
    loadImage();
    
    // 添加画布点击事件监听
    canvas.on('mouse:down', (options: any) => {
      const pointer = canvas.getPointer(options.e);
      applyColorToArea(pointer.x, pointer.y, currentColor.value);
    });
  }
});

onUnmounted(() => {
  // 清理资源
  if (canvas) {
    canvas.dispose();
  }
});
</script>

<style scoped>
.coloring-app {
  display: flex;
  gap: 20px;
  padding: 20px;
}

.tools-panel {
  width: 200px;
  background-color: #f5f5f5;
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.color-picker h3 {
  margin-top: 0;
  margin-bottom: 10px;
}

.color-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-bottom: 15px;
}

.color-item {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  cursor: pointer;
  border: 2px solid transparent;
  transition: transform 0.2s;
}

.color-item:hover {
  transform: scale(1.1);
}

.color-item.active {
  border-color: #333;
}

input[type="color"] {
  width: 100%;
  height: 40px;
  margin-bottom: 15px;
}

.actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.action-btn {
  padding: 8px 12px;
  background-color: #4a90e2;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

.action-btn:hover {
  background-color: #3a80d2;
}

.canvas-container {
  flex: 1;
  border: 1px solid #ddd;
  border-radius: 8px;
  overflow: hidden;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

canvas {
  display: block;
}
</style>